{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "922edb90",
   "metadata": {},
   "source": [
    "# Day 2：pandas 入门（数据结构与导入）\n",
    "\n",
    "> 今日目标：掌握 Series / DataFrame 基本概念、创建方式、读取 CSV，完成列/行选择、新增列、基础统计。\n",
    "学习路径：\n",
    "0. numpy 入门（数组基础）\n",
    "1. 为什么需要 pandas\n",
    "2. Series 与 DataFrame 概念 & 快速创建\n",
    "3. 读取 CSV 并初步查看数据\n",
    "4. 列 / 行 选取与切片\n",
    "5. 新增列（含单位换算示例）\n",
    "6. 基础统计（mean / max / value_counts）\n",
    "7. Mini Case：找出 PM2.5 均值最高的 3 个城市\n",
    "8. 小结\n",
    "9. 课后作业提示\n",
    "\n",
    "> 建议：每完成一个模块，自己新增一小段变形练习（例如换个列名、换个筛选条件）。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d47392d9",
   "metadata": {},
   "source": [
    "## 0. numpy 入门（数组基础）\n",
    "\n",
    "Numpy 是 Python 科学计算的基础库，pandas 的底层数据结构就是基于 numpy 数组。\n",
    "\n",
    "### 0.1 导入与数组创建\n",
    "- 常用别名：`import numpy as np`\n",
    "- 创建一维/二维数组：`np.array`\n",
    "- 常用初始化：`np.zeros`, `np.ones`, `np.arange`, `np.linspace`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "04a57173",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "一维数组: [1 2 3 4]\n",
      "二维数组:\n",
      " [[1 2 3]\n",
      " [4 5 6]]\n",
      "全零:\n",
      " [[0. 0. 0.]\n",
      " [0. 0. 0.]]\n",
      "全一:\n",
      " [[1. 1. 1.]\n",
      " [1. 1. 1.]]\n",
      "arange: [0 2 4 6 8]\n",
      "linspace: [0.   0.25 0.5  0.75 1.  ]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "# 一维数组\n",
    "a = np.array([1, 2, 3, 4])\n",
    "print('一维数组:', a)\n",
    "\n",
    "# 二维数组\n",
    "b = np.array([[1, 2, 3], [4, 5, 6]])\n",
    "print('二维数组:\\n', b)\n",
    "\n",
    "# 全零/全一数组\n",
    "z = np.zeros((2, 3))\n",
    "o = np.ones((2, 3))\n",
    "print('全零:\\n', z)\n",
    "print('全一:\\n', o)\n",
    "\n",
    "# 等差数组\n",
    "ar = np.arange(0, 10, 2)  # 步长为2\n",
    "print('arange:', ar)\n",
    "\n",
    "# 等间隔数组\n",
    "lin = np.linspace(0, 1, 5)  # 5个点，含头尾\n",
    "print('linspace:', lin)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bd4788e0",
   "metadata": {},
   "source": [
    "### 0.2 数组属性与形状\n",
    "- `shape`：数组的维度\n",
    "- `dtype`：元素类型\n",
    "- `ndim`：维度数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "76a1a137",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "b =\n",
      " [[1. 2. 3.]\n",
      " [4. 5. 6.]]\n",
      "b.shape = (2, 3)\n",
      "b.dtype = float64\n",
      "b.ndim = 2\n"
     ]
    }
   ],
   "source": [
    "b = np.array([[1.0, 2, 3], [4, 5, 6]])\n",
    "print('b =\\n', b)\n",
    "print('b.shape =', b.shape)\n",
    "print('b.dtype =', b.dtype)\n",
    "print('b.ndim =', b.ndim)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c95d2e8a",
   "metadata": {},
   "source": [
    "### 0.3 索引与切片\n",
    "- 与 Python 列表类似，支持切片、步长\n",
    "- 多维数组用逗号分隔索引"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "9a3418db",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a = [1 2 3 4]\n",
      "a[1:3] = [2 3]\n",
      "------------------------------\n",
      "b =\n",
      " [[1. 2. 3.]\n",
      " [4. 5. 6.]]\n",
      "b[0, 1] = 2.0\n",
      "b[1, :] = [4. 5. 6.]\n",
      "b[:, 2] = [3. 6.]\n"
     ]
    }
   ],
   "source": [
    "a = np.array([1, 2, 3, 4])\n",
    "print('a =', a)\n",
    "# 一维切片\n",
    "print('a[1:3] =', a[1:3])\n",
    "print('-'*30)\n",
    "\n",
    "b = np.array([[1.0, 2, 3], [4, 5, 6]])\n",
    "print('b =\\n', b)\n",
    "# 二维索引\n",
    "print('b[0, 1] =', b[0, 1])\n",
    "print('b[1, :] =', b[1, :])\n",
    "print('b[:, 2] =', b[:, 2])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2a52b400",
   "metadata": {},
   "source": [
    "### 0.4 基础运算与广播\n",
    "- 支持数组间和标量的加减乘除\n",
    "- 广播：不同形状自动扩展参与运算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "eadeb196",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a = [1 2 3 4]\n",
      "------------------------------\n",
      "a + 10 = [11 12 13 14]\n",
      "a * 2 = [2 4 6 8]\n",
      "a + [10, 20, 30, 40] = [11 22 33 44]\n",
      "------------------------------\n",
      "b =\n",
      " [[1. 2. 3.]\n",
      " [4. 5. 6.]]\n",
      "------------------------------\n",
      "b + 1 =\n",
      " [[2. 3. 4.]\n",
      " [5. 6. 7.]]\n",
      "------------------------------\n",
      "b + [10, 20, 30] =\n",
      " [[11. 22. 33.]\n",
      " [14. 25. 36.]]\n",
      "------------------------------\n",
      "b + [[1], [2]] =\n",
      " [[2. 3. 4.]\n",
      " [6. 7. 8.]]\n",
      "------------------------------\n"
     ]
    }
   ],
   "source": [
    "a = np.array([1, 2, 3, 4])\n",
    "print('a =', a)\n",
    "print('-'*30)\n",
    "\n",
    "# 一维广播\n",
    "print('a + 10 =', a + 10)\n",
    "print('a * 2 =', a * 2)\n",
    "print('a + [10, 20, 30, 40] =', a + np.array([10, 20, 30, 40]))\n",
    "print('-'*30)\n",
    "\n",
    "b = np.array([[1.0, 2, 3], [4, 5, 6]])\n",
    "print('b =\\n', b)\n",
    "print('-'*30)\n",
    "# 二维广播\n",
    "print('b + 1 =\\n', b + 1)\n",
    "print('-'*30)\n",
    "print('b + [10, 20, 30] =\\n', b + np.array([10, 20, 30]))\n",
    "print('-'*30)\n",
    "print('b + [[1], [2]] =\\n', b + np.array([[1], [2]]))\n",
    "print('-'*30)\n",
    "# print('b + [1, 2] =\\n', b + np.array([1, 2]))\n",
    "# print('-'*30)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3ea8dbdd",
   "metadata": {},
   "source": [
    "### 0.5 常用统计与逻辑运算\n",
    "- 求和/均值/最大值：`sum`, `mean`, `max`\n",
    "- 布尔过滤：`a[a > 2]`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "1d808ea0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "a.sum() = 10\n",
      "a.mean() = 2.5\n",
      "a.max() = 4\n",
      "a > 2: [False False  True  True]\n",
      "a[a > 2] = [3 4]\n",
      "b > 2:\n",
      " [[False False  True]\n",
      " [ True  True  True]]\n",
      "b[b > 2] = [3. 4. 5. 6.]\n"
     ]
    }
   ],
   "source": [
    "print('a.sum() =', a.sum())\n",
    "print('a.mean() =', a.mean())\n",
    "print('a.max() =', a.max())\n",
    "\n",
    "# 布尔过滤\n",
    "print('a > 2:', a > 2)\n",
    "print('a[a > 2] =', a[a > 2])\n",
    "\n",
    "# 二维过滤\n",
    "print('b > 2:\\n', b > 2)\n",
    "print('b[b > 2] =', b[b > 2])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f0bcf144",
   "metadata": {},
   "source": [
    "## 1. 为什么需要 pandas?\n",
    "昨天我们用 list + dict 组织了一个简易表格。问题：\n",
    "- 代码遍历冗长，容易出错\n",
    "- 统计 / 筛选 / 排序需要自己写循环\n",
    "\n",
    "pandas 提供：\n",
    "- 更直观的表格结构 (DataFrame)\n",
    "- 一行代码完成常见统计\n",
    "- 自动对齐、处理缺失值机制\n",
    "- 读取/导出多种格式 (CSV, Excel, JSON...)\n",
    "\n",
    "一句话：**让数据整理 + 分析更高效**。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7f7f467a",
   "metadata": {},
   "source": [
    "## 2. Series 与 DataFrame 概念 & 快速创建\n",
    "- Series：一列数据 + 索引 (带标签的一维数组)。\n",
    "- DataFrame：多列组成的二维表 (共享行索引)。\n",
    "\n",
    "下面通过字典与列表快速创建。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "id": "832e6f33",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Series:\n",
      "0    10\n",
      "1    20\n",
      "2    30\n",
      "Name: 示例列, dtype: int64\n",
      "索引 index: RangeIndex(start=0, stop=3, step=1)\n",
      "DataFrame:\n",
      "   城市  PM25\n",
      "0  广州    42\n",
      "1  深圳    35\n",
      "2  佛山    50\n",
      "列名 columns: Index(['城市', 'PM25'], dtype='object')\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd  # 通常约定写法\n",
    "\n",
    "# 创建一个 Series\n",
    "s = pd.Series([10, 20, 30], name='示例列')\n",
    "print('Series:')\n",
    "print(s)\n",
    "print('索引 index:', s.index)\n",
    "\n",
    "# 创建一个 DataFrame (字典 key=列名, value=列表)\n",
    "data = {\n",
    "    '城市': ['广州', '深圳', '佛山'],\n",
    "    'PM25': [42, 35, 50]\n",
    "}\n",
    "df_small = pd.DataFrame(data)\n",
    "print('DataFrame:')\n",
    "print(df_small)\n",
    "print('列名 columns:', df_small.columns)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "id": "7532b1c7",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.microsoft.datawrangler.viewer.v0+json": {
       "columns": [
        {
         "name": "index",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "城市",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "PM25",
         "rawType": "int64",
         "type": "integer"
        }
       ],
       "ref": "87fbdb07-d049-4a8e-b068-d4b8dd3b8614",
       "rows": [
        [
         "0",
         "广州",
         "42"
        ],
        [
         "1",
         "深圳",
         "35"
        ],
        [
         "2",
         "佛山",
         "50"
        ]
       ],
       "shape": {
        "columns": 2,
        "rows": 3
       }
      },
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>城市</th>\n",
       "      <th>PM25</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>广州</td>\n",
       "      <td>42</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>深圳</td>\n",
       "      <td>35</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>佛山</td>\n",
       "      <td>50</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   城市  PM25\n",
       "0  广州    42\n",
       "1  深圳    35\n",
       "2  佛山    50"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# DataFrame 还可以从“列表 + 字典”结构构建：\n",
    "records = [\n",
    "    {'城市': '广州', 'PM25': 42},\n",
    "    {'城市': '深圳', 'PM25': 35},\n",
    "    {'城市': '佛山', 'PM25': 50}\n",
    "]\n",
    "df_from_records = pd.DataFrame(records)\n",
    "df_from_records"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8d10f0c4",
   "metadata": {},
   "source": [
    "## 3. 读取 CSV 并初步查看数据\n",
    "### CSV 格式简介\n",
    "CSV（Comma-Separated Values，逗号分隔值）是一种常见的表格数据存储格式。每一行为一条记录，字段之间用逗号分隔。\n",
    "- **扩展名**：.csv\n",
    "- **结构示例**：\n",
    "```csv\n",
    "city,PM25,PM10,NO2,province\n",
    "广州,42,60,18,广东\n",
    "深圳,35,50,20,广东\n",
    "佛山,50,70,22,广东\n",
    "```\n",
    "- **常见特性**：\n",
    "  - 第一行为表头（字段名）\n",
    "  - 字段之间用英文逗号分隔\n",
    "  - 字符串字段可用引号包裹（如遇逗号或换行）\n",
    "  - 缺失值通常留空（,,）或用特殊标记（如NA）\n",
    "- **注意事项**：\n",
    "  - 不同地区可能用分号、制表符等分隔（可用参数 sep 指定）\n",
    "  - 编码格式常见为 UTF-8 或 GBK（中文 Windows 下常见 GBK）\n",
    "  - 字段内容如包含逗号、换行等特殊字符，需用引号包裹\n",
    "\n",
    "我们使用提供的 `air_quality_simple.csv`。步骤：\n",
    "1. read_csv 读取\n",
    "2. head() 查看前几行\n",
    "3. info() 了解列与数据类型\n",
    "4. shape / dtypes 查看形状与类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f7a6865c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.microsoft.datawrangler.viewer.v0+json": {
       "columns": [
        {
         "name": "index",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "city",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "province",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "PM25",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "PM10",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "NO2",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "SO2",
         "rawType": "int64",
         "type": "integer"
        }
       ],
       "ref": "5701208e-bdfa-421c-a91c-ddda831c4ef1",
       "rows": [
        [
         "0",
         "广州",
         "广东",
         null,
         "55",
         "19",
         "7"
        ],
        [
         "1",
         "深圳",
         "广东",
         "35.0",
         "48",
         "17",
         "6"
        ],
        [
         "2",
         "佛山",
         "广东",
         "50.0",
         "70",
         "23",
         "9"
        ],
        [
         "3",
         "北京",
         "北京",
         "60.0",
         "80",
         "35",
         "12"
        ],
        [
         "4",
         "上海",
         "上海",
         "45.0",
         "62",
         "28",
         "10"
        ]
       ],
       "shape": {
        "columns": 6,
        "rows": 5
       }
      },
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>city</th>\n",
       "      <th>province</th>\n",
       "      <th>PM25</th>\n",
       "      <th>PM10</th>\n",
       "      <th>NO2</th>\n",
       "      <th>SO2</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>广州</td>\n",
       "      <td>广东</td>\n",
       "      <td>NaN</td>\n",
       "      <td>55</td>\n",
       "      <td>19</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>深圳</td>\n",
       "      <td>广东</td>\n",
       "      <td>35.0</td>\n",
       "      <td>48</td>\n",
       "      <td>17</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>佛山</td>\n",
       "      <td>广东</td>\n",
       "      <td>50.0</td>\n",
       "      <td>70</td>\n",
       "      <td>23</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>北京</td>\n",
       "      <td>北京</td>\n",
       "      <td>60.0</td>\n",
       "      <td>80</td>\n",
       "      <td>35</td>\n",
       "      <td>12</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>上海</td>\n",
       "      <td>上海</td>\n",
       "      <td>45.0</td>\n",
       "      <td>62</td>\n",
       "      <td>28</td>\n",
       "      <td>10</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  city province  PM25  PM10  NO2  SO2\n",
       "0   广州       广东   NaN    55   19    7\n",
       "1   深圳       广东  35.0    48   17    6\n",
       "2   佛山       广东  50.0    70   23    9\n",
       "3   北京       北京  60.0    80   35   12\n",
       "4   上海       上海  45.0    62   28   10"
      ]
     },
     "execution_count": 33,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 读取数据 (路径相对于项目根目录)\n",
    "air = pd.read_csv('../data/air_quality_simple.csv') # read_excel()\n",
    "# 查看前 5 行\n",
    "air.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "cc40d3f7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "形状 shape = (10, 6)\n",
      "列类型 dtypes:\n",
      "city         object\n",
      "province     object\n",
      "PM25        float64\n",
      "PM10          int64\n",
      "NO2           int64\n",
      "SO2           int64\n",
      "dtype: object\n",
      "info():\n",
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 10 entries, 0 to 9\n",
      "Data columns (total 6 columns):\n",
      " #   Column    Non-Null Count  Dtype  \n",
      "---  ------    --------------  -----  \n",
      " 0   city      10 non-null     object \n",
      " 1   province  10 non-null     object \n",
      " 2   PM25      9 non-null      float64\n",
      " 3   PM10      10 non-null     int64  \n",
      " 4   NO2       10 non-null     int64  \n",
      " 5   SO2       10 non-null     int64  \n",
      "dtypes: float64(1), int64(3), object(2)\n",
      "memory usage: 612.0+ bytes\n",
      "None\n"
     ]
    }
   ],
   "source": [
    "# 数据概况\n",
    "print('形状 shape =', air.shape)  # (行数, 列数)\n",
    "print('列类型 dtypes:')\n",
    "print(air.dtypes)\n",
    "print('info():')\n",
    "print(air.info())  # info 自带输出返回 None"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fc2c3f12",
   "metadata": {},
   "source": [
    "### 小练习 1 (自己动手)\n",
    "1. 使用 head(3) 只看前三行。\n",
    "2. 使用 tail(2) 查看最后两行。\n",
    "3. 观察哪几列是数值型。\n",
    "\n",
    "(自行在下方新建单元格)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d0908dd0",
   "metadata": {},
   "source": [
    "## 4. 列 / 行 选取与切片\n",
    "常用方式：\n",
    "- 取单列：df['列名'] (得到 Series)\n",
    "- 取多列：df[['列1','列2']]\n",
    "- 行定位：iloc 按位置 / loc 按标签 (我们当前行标签是默认 0,1,2,...)\n",
    "- 切片：df.iloc[行起:行止]  类似 Python 列表切片 (不含行止)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "25eaebfe",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PM2.5 列前 5 个值: [nan, 35.0, 50.0, 60.0, 45.0]\n"
     ]
    },
    {
     "data": {
      "application/vnd.microsoft.datawrangler.viewer.v0+json": {
       "columns": [
        {
         "name": "index",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "city",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "PM25",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "PM10",
         "rawType": "int64",
         "type": "integer"
        }
       ],
       "ref": "44288556-2779-4a5d-b48c-e4571a0aa498",
       "rows": [
        [
         "0",
         "广州",
         null,
         "55"
        ],
        [
         "1",
         "深圳",
         "35.0",
         "48"
        ],
        [
         "2",
         "佛山",
         "50.0",
         "70"
        ]
       ],
       "shape": {
        "columns": 3,
        "rows": 3
       }
      },
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>city</th>\n",
       "      <th>PM25</th>\n",
       "      <th>PM10</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>广州</td>\n",
       "      <td>NaN</td>\n",
       "      <td>55</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>深圳</td>\n",
       "      <td>35.0</td>\n",
       "      <td>48</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>佛山</td>\n",
       "      <td>50.0</td>\n",
       "      <td>70</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  city  PM25  PM10\n",
       "0   广州   NaN    55\n",
       "1   深圳  35.0    48\n",
       "2   佛山  50.0    70"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 取单列 (Series)\n",
    "pm25 = air['PM25']\n",
    "print('PM2.5 列前 5 个值:', pm25.head().tolist())\n",
    "\n",
    "# 取多列 (仍是 DataFrame)\n",
    "subset = air[['city', 'PM25', 'PM10']]\n",
    "subset.head(3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "id": "cb1de790",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "第一行 city = 广州\n"
     ]
    },
    {
     "data": {
      "application/vnd.microsoft.datawrangler.viewer.v0+json": {
       "columns": [
        {
         "name": "index",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "city",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "province",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "PM25",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "PM10",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "NO2",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "SO2",
         "rawType": "int64",
         "type": "integer"
        }
       ],
       "ref": "31ba1cef-867f-4127-a426-edf98203874f",
       "rows": [
        [
         "0",
         "广州",
         "广东",
         null,
         "55",
         "19",
         "7"
        ],
        [
         "1",
         "深圳",
         "广东",
         "35.0",
         "48",
         "17",
         "6"
        ],
        [
         "2",
         "佛山",
         "广东",
         "50.0",
         "70",
         "23",
         "9"
        ]
       ],
       "shape": {
        "columns": 6,
        "rows": 3
       }
      },
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>city</th>\n",
       "      <th>province</th>\n",
       "      <th>PM25</th>\n",
       "      <th>PM10</th>\n",
       "      <th>NO2</th>\n",
       "      <th>SO2</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>广州</td>\n",
       "      <td>广东</td>\n",
       "      <td>NaN</td>\n",
       "      <td>55</td>\n",
       "      <td>19</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>深圳</td>\n",
       "      <td>广东</td>\n",
       "      <td>35.0</td>\n",
       "      <td>48</td>\n",
       "      <td>17</td>\n",
       "      <td>6</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>佛山</td>\n",
       "      <td>广东</td>\n",
       "      <td>50.0</td>\n",
       "      <td>70</td>\n",
       "      <td>23</td>\n",
       "      <td>9</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  city province  PM25  PM10  NO2  SO2\n",
       "0   广州       广东   NaN    55   19    7\n",
       "1   深圳       广东  35.0    48   17    6\n",
       "2   佛山       广东  50.0    70   23    9"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 行选取：第 0 行、第 0~2 行、特定行集合\n",
    "row0 = air.iloc[0]  # 第一行 Series iloc = index location\n",
    "print('第一行 city =', row0['city'])\n",
    "\n",
    "rows_0_3 = air.iloc[0:3]  # 0,1,2 行\n",
    "rows_0_3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "82ad2c99",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.microsoft.datawrangler.viewer.v0+json": {
       "columns": [
        {
         "name": "index",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "city",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "province",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "PM25",
         "rawType": "float64",
         "type": "float"
        }
       ],
       "ref": "ee786576-2a42-4536-a566-19f024318891",
       "rows": [
        [
         "0",
         "广州",
         "广东",
         null
        ],
        [
         "1",
         "深圳",
         "广东",
         "35.0"
        ],
        [
         "2",
         "佛山",
         "广东",
         "50.0"
        ]
       ],
       "shape": {
        "columns": 3,
        "rows": 3
       }
      },
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>city</th>\n",
       "      <th>province</th>\n",
       "      <th>PM25</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>广州</td>\n",
       "      <td>广东</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>深圳</td>\n",
       "      <td>广东</td>\n",
       "      <td>35.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>佛山</td>\n",
       "      <td>广东</td>\n",
       "      <td>50.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  city province  PM25\n",
       "0   广州       广东   NaN\n",
       "1   深圳       广东  35.0\n",
       "2   佛山       广东  50.0"
      ]
     },
     "execution_count": 37,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 同时选行列：iloc[行切片, 列切片] 例如前 3 行 + 前 3 列\n",
    "air.iloc[0:3, 0:3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "8ba7e0e3",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.microsoft.datawrangler.viewer.v0+json": {
       "columns": [
        {
         "name": "学号",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "姓名",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "语文",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "数学",
         "rawType": "object",
         "type": "unknown"
        },
        {
         "name": "英语",
         "rawType": "float64",
         "type": "float"
        }
       ],
       "ref": "1ebd22c6-c852-4466-9bd6-009bbe124260",
       "rows": [
        [
         "2401",
         "张三",
         "59",
         "59..5",
         "60.5"
        ],
        [
         "2402",
         "李四",
         "90",
         "95",
         "100.0"
        ],
        [
         "2403",
         "王五",
         "95",
         "100",
         "90.0"
        ]
       ],
       "shape": {
        "columns": 4,
        "rows": 3
       }
      },
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>姓名</th>\n",
       "      <th>语文</th>\n",
       "      <th>数学</th>\n",
       "      <th>英语</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>学号</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2401</th>\n",
       "      <td>张三</td>\n",
       "      <td>59</td>\n",
       "      <td>59..5</td>\n",
       "      <td>60.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2402</th>\n",
       "      <td>李四</td>\n",
       "      <td>90</td>\n",
       "      <td>95</td>\n",
       "      <td>100.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2403</th>\n",
       "      <td>王五</td>\n",
       "      <td>95</td>\n",
       "      <td>100</td>\n",
       "      <td>90.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      姓名  语文     数学     英语\n",
       "学号                        \n",
       "2401  张三  59  59..5   60.5\n",
       "2402  李四  90     95  100.0\n",
       "2403  王五  95    100   90.0"
      ]
     },
     "execution_count": 41,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "score = pd.read_excel('../data/成绩单.xlsx', index_col='学号')\n",
    "score.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "90b3e77d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "Index: 3 entries, 2401 to 2403\n",
      "Data columns (total 4 columns):\n",
      " #   Column  Non-Null Count  Dtype  \n",
      "---  ------  --------------  -----  \n",
      " 0   姓名      3 non-null      object \n",
      " 1   语文      3 non-null      int64  \n",
      " 2   数学      3 non-null      object \n",
      " 3   英语      3 non-null      float64\n",
      "dtypes: float64(1), int64(1), object(2)\n",
      "memory usage: 120.0+ bytes\n"
     ]
    }
   ],
   "source": [
    "score.info()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "435dce74",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.microsoft.datawrangler.viewer.v0+json": {
       "columns": [
        {
         "name": "index",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "2401",
         "rawType": "object",
         "type": "unknown"
        }
       ],
       "ref": "4d646a50-3ad7-451a-af14-4c827299f703",
       "rows": [
        [
         "姓名",
         "张三"
        ],
        [
         "语文",
         "59"
        ],
        [
         "数学",
         "59..5"
        ],
        [
         "英语",
         "60.5"
        ]
       ],
       "shape": {
        "columns": 1,
        "rows": 4
       }
      },
      "text/plain": [
       "姓名       张三\n",
       "语文       59\n",
       "数学    59..5\n",
       "英语     60.5\n",
       "Name: 2401, dtype: object"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "score.iloc[0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "39664a30",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.microsoft.datawrangler.viewer.v0+json": {
       "columns": [
        {
         "name": "学号",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "姓名",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "语文",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "数学",
         "rawType": "object",
         "type": "unknown"
        },
        {
         "name": "英语",
         "rawType": "float64",
         "type": "float"
        }
       ],
       "ref": "2cbd1955-2ff8-4833-a0f7-87a4ab8409d2",
       "rows": [
        [
         "2401",
         "张三",
         "59",
         "59..5",
         "60.5"
        ],
        [
         "2402",
         "李四",
         "90",
         "95",
         "100.0"
        ],
        [
         "2403",
         "王五",
         "95",
         "100",
         "90.0"
        ]
       ],
       "shape": {
        "columns": 4,
        "rows": 3
       }
      },
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>姓名</th>\n",
       "      <th>语文</th>\n",
       "      <th>数学</th>\n",
       "      <th>英语</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>学号</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2401</th>\n",
       "      <td>张三</td>\n",
       "      <td>59</td>\n",
       "      <td>59..5</td>\n",
       "      <td>60.5</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2402</th>\n",
       "      <td>李四</td>\n",
       "      <td>90</td>\n",
       "      <td>95</td>\n",
       "      <td>100.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2403</th>\n",
       "      <td>王五</td>\n",
       "      <td>95</td>\n",
       "      <td>100</td>\n",
       "      <td>90.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      姓名  语文     数学     英语\n",
       "学号                        \n",
       "2401  张三  59  59..5   60.5\n",
       "2402  李四  90     95  100.0\n",
       "2403  王五  95    100   90.0"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "score.loc[2401:2403]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "04cae9d3",
   "metadata": {},
   "source": [
    "### 小练习 2\n",
    "1. 取出第 5~7 行的 city 与 PM10 列。\n",
    "2. 只取 province 列组成一个 Series 并查看唯一值 (unique)。\n",
    "3. 统计每个 province 出现次数 (使用 value_counts)。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "8a5c6d41",
   "metadata": {},
   "source": [
    "## 5. 新增列（单位换算示例）\n",
    "需求：假设 PM2.5 当前单位是 μg/m³，我们想换算成 mg/m³ (只为演示，实际意义不一定常用)。\n",
    "换算：1 mg = 1000 μg，因此 mg_value = 原值 / 1000。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "id": "ee1ce2ba",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.microsoft.datawrangler.viewer.v0+json": {
       "columns": [
        {
         "name": "index",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "city",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "PM25",
         "rawType": "float64",
         "type": "float"
        },
        {
         "name": "PM25_mg",
         "rawType": "float64",
         "type": "float"
        }
       ],
       "ref": "bf3785b4-3a24-4c19-9c20-7dad43547a9c",
       "rows": [
        [
         "0",
         "广州",
         null,
         null
        ],
        [
         "1",
         "深圳",
         "35.0",
         "0.035"
        ],
        [
         "2",
         "佛山",
         "50.0",
         "0.05"
        ],
        [
         "3",
         "北京",
         "60.0",
         "0.06"
        ],
        [
         "4",
         "上海",
         "45.0",
         "0.045"
        ]
       ],
       "shape": {
        "columns": 3,
        "rows": 5
       }
      },
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>city</th>\n",
       "      <th>PM25</th>\n",
       "      <th>PM25_mg</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>广州</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>深圳</td>\n",
       "      <td>35.0</td>\n",
       "      <td>0.035</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>佛山</td>\n",
       "      <td>50.0</td>\n",
       "      <td>0.050</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>北京</td>\n",
       "      <td>60.0</td>\n",
       "      <td>0.060</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>上海</td>\n",
       "      <td>45.0</td>\n",
       "      <td>0.045</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  city  PM25  PM25_mg\n",
       "0   广州   NaN      NaN\n",
       "1   深圳  35.0    0.035\n",
       "2   佛山  50.0    0.050\n",
       "3   北京  60.0    0.060\n",
       "4   上海  45.0    0.045"
      ]
     },
     "execution_count": 50,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 新增列：PM25_mg\n",
    "air['PM25_mg'] = air['PM25'] / 1000\n",
    "air[['city', 'PM25', 'PM25_mg']].head()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7c66a44f",
   "metadata": {},
   "source": [
    "### 补充：覆盖与删除列\n",
    "- 直接再次赋值可覆盖：air['PM25_mg'] = ...\n",
    "- 删除列：del air['PM25_mg'] 或 air.drop(columns=['PM25_mg'], inplace=True)\n",
    "(本课不强制要求掌握 inplace 细节，知道结果即可)。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "79bdd995",
   "metadata": {},
   "source": [
    "## 6. 基础统计 (mean / max / value_counts)\n",
    "常用：\n",
    "- 平均值 mean()\n",
    "- 最大/最小 max() / min()\n",
    "- 排序 sort_values()\n",
    "- 分类频次 value_counts() (Series 方法)\n",
    "\n",
    "我们来做：1) PM2.5 平均值 2) PM10 最大值对应城市 3) 各省份出现次数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "c68b74e4",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PM2.5 平均值 = 50.22\n",
      "PM10 最大值 = 85\n",
      "对应城市:\n",
      "  city  PM10\n",
      "9   西安    85\n"
     ]
    },
    {
     "data": {
      "application/vnd.microsoft.datawrangler.viewer.v0+json": {
       "columns": [
        {
         "name": "province",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "count",
         "rawType": "int64",
         "type": "integer"
        }
       ],
       "ref": "dc73e792-e89d-46ab-9a54-e14642d5334d",
       "rows": [
        [
         "广东",
         "3"
        ],
        [
         "北京",
         "1"
        ],
        [
         "上海",
         "1"
        ],
        [
         "浙江",
         "1"
        ],
        [
         "四川",
         "1"
        ],
        [
         "重庆",
         "1"
        ],
        [
         "湖北",
         "1"
        ],
        [
         "陕西",
         "1"
        ]
       ],
       "shape": {
        "columns": 1,
        "rows": 8
       }
      },
      "text/plain": [
       "province\n",
       "广东    3\n",
       "北京    1\n",
       "上海    1\n",
       "浙江    1\n",
       "四川    1\n",
       "重庆    1\n",
       "湖北    1\n",
       "陕西    1\n",
       "Name: count, dtype: int64"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "pm25_mean = air['PM25'].mean()\n",
    "print('PM2.5 平均值 =', round(pm25_mean, 2))\n",
    "\n",
    "# PM10 最大值与对应行\n",
    "pm10_max = air['PM10'].max()\n",
    "row_pm10_max = air[air['PM10'] == pm10_max]  # 布尔过滤\n",
    "print('PM10 最大值 =', pm10_max)\n",
    "print('对应城市:')\n",
    "print(row_pm10_max[['city', 'PM10']])\n",
    "\n",
    "# 省份计数\n",
    "province_counts = air['province'].value_counts()\n",
    "province_counts"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c8e79702",
   "metadata": {},
   "source": [
    "### 小练习 3\n",
    "1. 计算 NO2 的平均值与最大值。\n",
    "2. 按 PM25 排序取出前 5 行 (sort_values)。\n",
    "3. 计算 PM2.5 与 PM10 的差 (PM10 - PM25) 新增为一列。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5fd68b8e",
   "metadata": {},
   "source": [
    "## 7. Mini Case：找出 PM2.5 均值最高的 3 个城市\n",
    "需求：输出城市名称与对应 PM2.5 值。\n",
    "步骤：\n",
    "1. 按 PM25 降序排序\n",
    "2. 取前 3 行\n",
    "3. 只保留 city / PM25 列展示"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "2b51d127",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.microsoft.datawrangler.viewer.v0+json": {
       "columns": [
        {
         "name": "index",
         "rawType": "int64",
         "type": "integer"
        },
        {
         "name": "city",
         "rawType": "object",
         "type": "string"
        },
        {
         "name": "PM25",
         "rawType": "float64",
         "type": "float"
        }
       ],
       "ref": "a089bd00-2090-467c-b0a0-c85c5029c62d",
       "rows": [
        [
         "9",
         "西安",
         "63.0"
        ],
        [
         "3",
         "北京",
         "60.0"
        ],
        [
         "6",
         "成都",
         "58.0"
        ]
       ],
       "shape": {
        "columns": 2,
        "rows": 3
       }
      },
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>city</th>\n",
       "      <th>PM25</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>西安</td>\n",
       "      <td>63.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>北京</td>\n",
       "      <td>60.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>成都</td>\n",
       "      <td>58.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "  city  PM25\n",
       "9   西安  63.0\n",
       "3   北京  60.0\n",
       "6   成都  58.0"
      ]
     },
     "execution_count": 52,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "top3 = air.sort_values(by='PM25', ascending=False).head(3)[['city', 'PM25']]\n",
    "top3"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e5a9da54",
   "metadata": {},
   "source": [
    "拓展思考：如果以后有日期列，我们可以先 groupby 按城市求平均再排序。今天先不展开。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b3310e95",
   "metadata": {},
   "source": [
    "## 8. 课后作业提示\n",
    "请新建 *homework_day2.ipynb* 完成：\n",
    "1. 自己创建一个 “学习打卡” CSV（列：day,hours,activity），至少 7 行。\n",
    "2. 用 read_csv 读入后：\n",
    "   - 查看 head 与 info\n",
    "   - 新增列：hours_minutes = hours * 60\n",
    "   - 计算总学习时长与平均每天学习时长\n",
    "   - 找出学习时长最长那天 (排序或 idxmax)\n",
    "3. 写 80 字：分析你在哪些天效率更高，是否存在偏科 (某 activity 占比很高)。\n",
    "4. 额外加分 (可选)：value_counts(normalize=True) 统计各 activity 占比。\n",
    "\n",
    "提交要求：保证运行顺序从上到下不会报错，标注每一步标题。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7649cb92",
   "metadata": {},
   "source": [
    "---\n",
    "📌 提示：Day 3 将进入数据清洗 (缺失/重复/类型转换)。今天的练习请务必熟悉列选取与排序，否则后面会累积困难。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1e9a06ac",
   "metadata": {},
   "source": [
    "## 8. 小结\n",
    "今日回顾：\n",
    "1. 理解 pandas 两大核心结构：Series（一列）与 DataFrame（二维表）。\n",
    "2. 读写与初探：read_csv / head / info / dtypes / shape。\n",
    "3. 选取：单列、多列、iloc/loc、切片与布尔过滤雏形。\n",
    "4. 新增列：直接赋值；单位换算示例加深“列=向量”概念。\n",
    "5. 基础统计：mean / max / value_counts / sort_values 支撑快速洞察。\n",
    "6. Mini Case 体现“排序→取前N→选列”组合思路。\n",
    "\n",
    "方法提醒：始终先“查看(head/info)”再“操作”，确保对数据结构心里有数。\n",
    "下一步衔接：熟悉这些基本操作后，Day 3 才能高效定位并处理缺失与重复。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "d820bb1d",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 进阶/易错示例集合\n",
    "import pandas as pd\n",
    "air = pd.read_csv('../data/air_quality_simple.csv')\n",
    "\n",
    "# 1. 链式赋值警示示例（演示，不一定触发）：\n",
    "tmp = air[air['PM25'] > 40]\n",
    "# 正确：copy 再操作\n",
    "tmp2 = air[air['PM25'] > 40].copy()\n",
    "tmp2['PM25_mg'] = tmp2['PM25'] / 1000\n",
    "\n",
    "# 2. query 用法：\n",
    "high_pm = air.query('PM25 > 55 or PM10 > 80')[['city','PM25','PM10']].head()\n",
    "print('query 结果示例:\\n', high_pm)\n",
    "\n",
    "# 3. 多列排序：\n",
    "sorted_multi = air.sort_values(['PM25','PM10'], ascending=[False, True]).head()\n",
    "print('多列排序:\\n', sorted_multi[['city','PM25','PM10']])\n",
    "\n",
    "# 4. rename + assign + 计算差值：\n",
    "air2 = (air.rename(columns={'PM25':'PM25_val'})\n",
    "         .assign(PM_diff=lambda d: d['PM10'] - d['PM25_val']))\n",
    "print(air2[['city','PM25_val','PM10','PM_diff']].head())\n",
    "\n",
    "# 5. 分组占比：\n",
    "province_pct = air['province'].value_counts(normalize=True).round(3)\n",
    "print('省份占比:\\n', province_pct)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f05344a2",
   "metadata": {},
   "source": [
    "### 常见易错点与进阶示例 (阅读 + 练习)\n",
    "1. 复制 vs 视图：链式写法可能触发 SettingWithCopyWarning，应显式使用 .copy()。\n",
    "2. 布尔过滤组合：用括号包裹条件；可使用 query 简化语法。\n",
    "3. 频次占比：value_counts(normalize=True) 返回比例。\n",
    "4. 多列排序：sort_values(['PM25','PM10'], ascending=[False, True])。\n",
    "5. 重命名：rename(columns={'PM25':'PM25_val'})；批量可用字典。\n",
    "6. 索引设置：set_index('city') 便于基于标签选择，reset_index() 还原。\n",
    "7. assign 链式新增：df.assign(PM_diff=lambda d: d.PM10-d.PM25)。\n",
    "8. 选择列模式：显式列清单 columns_keep = [...] 再 df[columns_keep]，利于保持稳定。\n",
    "9. 分组再排序：groupby('province')['PM25'].mean().sort_values(ascending=False)\n",
    "10. 内存/类型优化：数值整型不含缺失可转为更小类型 (astype('int32')) (了解即可)。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "base",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
